﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.IO;

namespace XmlSplitter
{
    public class XmlSplit
    {
        #region Properties
        string XmlTag;
        XDocument xDoc;
        XElement[] Elements;
        string rootElement;
        XName insertToElement;
        #endregion

        public XmlSplit(string xmlTag)
        {
            XmlTag = xmlTag;
        }
        
        public void Exec(string filename, string dir, int limit)
        {
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            xDoc = XDocument.Parse(File.ReadAllText(filename, Encoding.Default));
            string fnbase = Path.GetFileNameWithoutExtension(filename);
            //
            rootElement = Tools.PrepareClearRoot(xDoc, XmlTag, out insertToElement);
            Elements = xDoc.Descendants(Tools.GetXName(XmlTag, xDoc)).ToArray();
            

            int count = Elements.Length;
            
            WriteLog($"Total elements: {count} Total files: {(count / limit) + 1}");

            DoParallel(dir, fnbase, limit);
            
        }

        void DoParallel(string dir, string fnbase, int limit)
        {
            int count = Elements.Length;
            Parallel.For(0, (count / limit) + 1, loop =>
            {
                var els = GetElements(limit, loop);
                WriteLog($"Saving file {loop + 1}...");
                SaveToFile(dir, fnbase, els, (loop + 1));
            });
        }
        
        void WriteLog(string msg, bool line = true)
        {
            if (line)
            {
                Console.WriteLine(msg);
            }
            else
            {
                Console.Write(msg);
            }
        }

        XElement[] GetElements(int limit, int loop)
        {
            return Elements.Skip(limit * loop).Take(limit).ToArray();
        }
                

        private void SaveToFile(string dir, string fnbase, IEnumerable<XElement> els, int i)
        {
            var fullFileName = Path.Combine(dir, string.Format("{1}-part{0}.xml", i, fnbase));
            var xd = XDocument.Parse(rootElement);
            xd.Descendants(insertToElement).First().Add(els);
            File.WriteAllText(fullFileName, xd.ToString(), Encoding.Default);
            
            // this method did wrong encoding...
            //xd.Save(fullFileName);
        }
    }
}
